package com.freewater.cargotracker.infrastructure.persistence.mybatis.repository;

import com.freewater.cargotracker.domain.model.location.Location;
import com.freewater.cargotracker.domain.model.location.LocationRepository;
import com.freewater.cargotracker.domain.model.location.UnLocode;
import com.freewater.cargotracker.infrastructure.persistence.mybatis.converter.LocationConverter;
import com.freewater.cargotracker.infrastructure.persistence.mybatis.dbobject.LocationPO;
import com.freewater.cargotracker.infrastructure.persistence.mybatis.mapper.LocationMapper;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Repository
public class LocationRepositoryImpl implements LocationRepository {

    private final LocationMapper locationMapper;

    public LocationRepositoryImpl(LocationMapper locationMapper) {
        this.locationMapper = locationMapper;
    }

    @Override
    public void save(Location location) {
        final LocationPO locationPO = LocationConverter.serialize(location);
        this.locationMapper.insert(locationPO);
        location.setId(locationPO.getId());
    }

    @Override
    public void saveAll(List<Location> locations) {
        if (locations.isEmpty()) {
            return;
        }
        final Map<LocationPO, Location> locationMap = new HashMap<>();
        locations.forEach(location -> {
            final LocationPO locationPO = LocationConverter.serialize(location);
            locationMap.put(locationPO, location);
        });
        this.locationMapper.insertAll(new ArrayList<>(locationMap.keySet()));
        locationMap.forEach(((locationPO, location) -> location.setId(locationPO.getId())));
    }

    @Override
    public Location findByCode(UnLocode unLocode) {
        final LocationPO locationPO = this.locationMapper.find(unLocode.getCode());
        return LocationConverter.deserialize(locationPO);
    }

    @Override
    public List<Location> findAll() {
        final List<LocationPO> locationPOs = this.locationMapper.findAll();
        return locationPOs.stream().map(LocationConverter::deserialize).collect(Collectors.toList());
    }
}
